package com.gary.spring.proxy;

import org.aopalliance.intercept.MethodInterceptor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.DefaultPointcutAdvisor;

/**
 * @author peng_rui
 * @date 2022/7/5
 */
public class SpringProxyDemo {
    public static void main(String[] args) {

        //切面：aspect advisor
        //通常使用的时aspect ， 而 advisor 是更加细粒度的切面，使用aspect最终也会被拆解成advisor

        //1 准备切点
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        pointcut.setExpression("execution(* foo())");
        //2 准备通知
        MethodInterceptor advice = invocation -> {
            System.out.println("before ...");
            Object proceed = invocation.proceed();
            System.out.println("after ...");
            return proceed;
        };
        //3 准备切面
        DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut, advice);

        /*
            创建代理 spring的选择
                a proxyTargetClass = false, 目标类实现了接口, 使用jdk代理
                b proxyTargetClass = false, 目标类没有实现接口, 使用cglib
                c proxyTargetClass = true, 总是使用cglib
         */
        //4 创建代理
        Target1 target1 = new Target1();
        ProxyFactory factory = new ProxyFactory();
        factory.setTarget(target1);
        factory.addAdvisors(advisor);
        factory.setInterfaces(target1.getClass().getInterfaces());
        factory.setProxyTargetClass(true);
        I1 proxy = (I1) factory.getProxy();
        System.out.println(proxy.getClass());
        proxy.foo();
        proxy.bar();
    }

    static class Target1 implements I1 {

        @Override
        public void foo() {
            System.out.println("target1 foo");
        }

        @Override
        public void bar() {
            System.out.println("target1 bar");
        }
    }

    interface I1 {
        void foo();

        void  bar();
    }
}
